<template>
  <div ref="boxRef" class="chart-box pie-box">
    <div class="chart-header">
      <h3>
        <span class="title-icon">|</span>
        <span>热销商品的占比</span>
      </h3>
      <button class="fullscreen-btn" @click="toggleFullscreen">⛶</button>
    </div>
    <div v-if="categoryOptions.length" class="pie-toolbar">
      <button
        class="arrow-btn"
        :disabled="categoryOptions.length <= 1"
        @click="switchCategory(-1)"
      >
        ‹
      </button>
      <div class="category-chips">
        <span
          v-for="(category, index) in categoryOptions"
          :key="category.label"
          class="chip"
          :class="{ active: index === activeCategoryIndex }"
          @click="selectCategory(index)"
        >
          {{ category.label }}
        </span>
      </div>
      <button
        class="arrow-btn"
        :disabled="categoryOptions.length <= 1"
        @click="switchCategory(1)"
      >
        ›
      </button>
    </div>
    <div ref="chartRef" class="chart"></div>
    <div class="pie-label"></div>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import { subscribeToChart } from '@/services/dataHub';

const props = defineProps<{ isDarkTheme: boolean }>();

const chartRef = ref<HTMLElement | null>(null);
const boxRef = ref<HTMLElement | null>(null);
let chart: echarts.ECharts | null = null;
let resizeHandler: (() => void) | null = null;
let fullscreenTimer: number | null = null;
let unsubscribe: (() => void) | null = null;
type HotNode = {
  name: string;
  value?: number;
  children?: HotNode[];
};

let originalData: HotNode[] = [];
const categoryOptions = ref<Array<{ label: string; nodes: HotNode[] }>>([]);
const activeCategoryIndex = ref(0);
const currentCategory = computed(() => categoryOptions.value[activeCategoryIndex.value]);

const decodeText = (text: string) => {
  try {
    return decodeURIComponent(escape(text));
  } catch (error) {
    return text;
  }
};

const disposeChart = () => {
  if (chart && !chart.isDisposed()) {
    chart.dispose();
  }
  chart = null;
};

// 获取热销商品数据（改用 WebSocket）
function setupHotDataSubscription() {
  unsubscribe = subscribeToChart('hot', (data: any) => {
    const list: HotNode[] = Array.isArray(data)
      ? data
      : Array.isArray(data?.data)
        ? data.data
        : Array.isArray(data?.value)
          ? data.value
          : [];

    // 只在数据长度变化时重置 activeCategoryIndex
    const oldLen = originalData.length;
    originalData = list;
    if (oldLen !== list.length) {
      activeCategoryIndex.value = 0;
    }
    categoryOptions.value = originalData.map((item) => ({
      label: decodeText(item.name),
      nodes: item.children && item.children.length ? item.children : [item],
    }));
    if (!categoryOptions.value.length) {
      categoryOptions.value = [{ label: '全部', nodes: originalData }];
    }
    updateChartOption();
  });
}

// 更新图表配置
function updateChartOption() {
  if (!chart) return;
  const category = currentCategory.value;
  if (!category) {
    chart.clear();
    return;
  }

  // 颜色数组
  const colors = ['#ff4757', '#3ae7d4', '#5dd465', '#ff6348', '#4a9eff', '#ffa940', '#c084fc', '#fb923c'];

  const flattenData: Array<{ name: string; value: number }> = [];

  const collect = (nodes: HotNode[]) => {
    nodes.forEach((node) => {
      const name = decodeText(node.name);
      if (node.children && node.children.length) {
        // 如果存在 children，则统计子节点的 value
        node.children.forEach((child) => {
          const childName = decodeText(child.name);
          const val = Number(child.value) || 0;
          if (childName && val > 0) {
            flattenData.push({ name: childName, value: val });
          }
        });
      } else {
        const val = Number(node.value) || 0;
        if (name && val > 0) {
          flattenData.push({ name, value: val });
        }
      }
    });
  };

  collect(category.nodes);

  if (!flattenData.length) {
    chart.clear();
    return;
  }

  const sorted = [...flattenData].sort((a, b) => b.value - a.value);
  const pieSource = sorted.slice(0, 12);

  const option: EChartsOption = {
    backgroundColor: 'transparent',
    tooltip: {
      trigger: 'item',
      formatter: (params: any) => {
        const percent = typeof params.percent === 'number' ? params.percent.toFixed(1) : params.percent;
        return `${params.name}<br/>占比：${percent}%`;
      },
    },
    legend: {
      orient: 'vertical',
      right: '5%',
      top: 'center',
      textStyle: { color: '#b0c4de', fontSize: 12 },
      itemWidth: 12,
      itemHeight: 12,
      icon: 'circle',
      data: pieSource.map((item) => item.name),
    },
    series: [
      {
        type: 'pie',
        radius: '65%',
        center: ['35%', '50%'],
        avoidLabelOverlap: false,
        data: pieSource.map((item, index) => ({
          value: item.value,
          name: item.name,
          itemStyle: { color: colors[index % colors.length] }
        })),
        label: {
          show: false,
        },
        labelLine: {
          show: false,
        },
        emphasis: {
          label: {
            show: false,
          },
          scale: true,
          scaleSize: 10,
        },
      },
    ],
  };

  chart.setOption(option);
}

const switchCategory = (direction: number) => {
  if (categoryOptions.value.length <= 1) return;
  const total = categoryOptions.value.length;
  activeCategoryIndex.value = (activeCategoryIndex.value + direction + total) % total;
};

const selectCategory = (index: number) => {
  if (index === activeCategoryIndex.value) return;
  if (index < 0 || index >= categoryOptions.value.length) return;
  activeCategoryIndex.value = index;
};

const initChart = () => {
  if (!chartRef.value) return;
  disposeChart();
  chart = echarts.init(chartRef.value);

  if (originalData.length) {
    updateChartOption();
  }

  if (!resizeHandler) {
    resizeHandler = () => chart?.resize();
    window.addEventListener('resize', resizeHandler);
  }
};

const toggleFullscreen = () => {
  const box = boxRef.value;
  if (!box) return;
  const button = box.querySelector('.fullscreen-btn') as HTMLButtonElement | null;

  if (!box.classList.contains('fullscreen')) {
    box.classList.add('fullscreen');
    if (button) button.textContent = '✕';
    fullscreenTimer = window.setTimeout(() => chart?.resize(), 300);
    window.addEventListener('keydown', escListener);
  } else {
    box.classList.remove('fullscreen');
    if (button) button.textContent = '⛶';
    fullscreenTimer = window.setTimeout(() => chart?.resize(), 300);
    window.removeEventListener('keydown', escListener);
  }
};

function escListener(e: KeyboardEvent) {
  if (e.key === 'Escape') {
    const box = boxRef.value;
    if (box && box.classList.contains('fullscreen')) {
      toggleFullscreen();
    }
  }
}

watch(
  () => props.isDarkTheme,
  () => {
    initChart();
  }
);

watch(activeCategoryIndex, () => {
  updateChartOption();
});

onMounted(() => {
  setupHotDataSubscription();
  initChart();
});

onUnmounted(() => {
  if (unsubscribe) {
    unsubscribe();
  }
  if (resizeHandler) {
    window.removeEventListener('resize', resizeHandler);
  }
  if (fullscreenTimer) {
    window.clearTimeout(fullscreenTimer);
  }
  window.removeEventListener('keydown', escListener);
  disposeChart();
});
</script>

<style scoped>
.pie-toolbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 8px 16px 0;
}

.arrow-btn {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid rgba(0, 150, 255, 0.4);
  background: transparent;
  color: #9fb0c6;
  cursor: pointer;
  transition: all 0.2s ease;
}

.arrow-btn:hover:enabled {
  color: #ffffff;
  border-color: rgba(0, 150, 255, 0.8);
  box-shadow: 0 0 8px rgba(0, 150, 255, 0.35);
}

.arrow-btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.category-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  max-width: calc(100% - 120px);
  justify-content: center;
}

.chip {
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #9fb0c6;
  font-size: 12px;
  cursor: pointer;
  transition: all 0.2s ease;
  white-space: nowrap;
}

.chip:hover {
  color: #ffffff;
  border-color: rgba(0, 150, 255, 0.6);
}

.chip.active {
  color: #ffffff;
  border-color: rgba(0, 150, 255, 0.9);
  background: rgba(0, 150, 255, 0.35);
  box-shadow: 0 0 10px rgba(0, 150, 255, 0.4);
}
</style>
